package com.zoe.onelink.util;


import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>标题: </p>
 * <p>描述: </p>
 * <p>版权: Copyright (c) 2021</p>
 * <p>公司: 智业软件股份有限公司</p>
 *
 * @version: 1.0
 * @author: ruansheng
 * @date: 2021-08-06
 */
public class StackTraceUtil {

    public static final Set<String> DEFAULT_STACK_TRACE_CLASS_NAME_PREFIX_SET;

    public static final Set<String> ONELINK_STACK_TRACE_CLASS_NAME_PREFIX_SET;

    static {
        DEFAULT_STACK_TRACE_CLASS_NAME_PREFIX_SET = Stream.of(
                "org.apache.catalina",
                "org.apache.dubbo.rpc",
                "org.springframework"
        ).collect(Collectors.toSet());
        ONELINK_STACK_TRACE_CLASS_NAME_PREFIX_SET = Stream.of("com.zoe").collect(Collectors.toSet());
    }

    /**
     * 根据规则过滤异常堆栈
     *
     * @param stackTraceElements 堆栈
     * @param include            true:包含 , false:排除
     */
    public static StackTraceElement[] cutStackTrace(StackTraceElement[] stackTraceElements, boolean include) {
        return cutStackTrace(stackTraceElements, DEFAULT_STACK_TRACE_CLASS_NAME_PREFIX_SET, include);
    }

    /**
     * 根据规则过滤异常堆栈
     *
     * @param stackTraceElements 堆栈
     * @param prefixSet          要过滤的包名前缀
     * @param include            true: 包含 , false: 排除
     */
    public static StackTraceElement[] cutStackTrace(StackTraceElement[] stackTraceElements, Set<String> prefixSet, boolean include) {
        if (stackTraceElements == null || stackTraceElements.length == 0 || prefixSet == null) {
            return new StackTraceElement[0];
        }
        List<StackTraceElement> list = new ArrayList<>(stackTraceElements.length);
        for (StackTraceElement stackTraceElement : stackTraceElements) {
            boolean matched = include ?
                    prefixSet.stream().anyMatch(prefix -> stackTraceElement.getClassName().startsWith(prefix)) :
                    prefixSet.stream().noneMatch(prefix -> stackTraceElement.getClassName().startsWith(prefix));
            if (matched) {
                list.add(stackTraceElement);
            }
        }
        return list.toArray(new StackTraceElement[0]);
    }

}
